/*
	This script file is part of the Sonic 3 A.I.R. script software distribution.
	Copyright (C) 2017-2024 by Eukaryot

	Published under the GNU GPLv3 open source software license, see license.txt
	or https://www.gnu.org/licenses/gpl-3.0.en.html
*/




// u16[A0 + 0x36] = Countdown until letting go the character(s)


//# address-hook(0x030ad0) end(0x030b52)
function void fn030ad0()
{
	objA0.render_flags |= render_flag.WORLD
	objA0.sprite_priority = 0x0200
	objA0.mapping_offset = 0x22f998
	objA0.sprite_attributes = (sprite_attribute.PALETTE.LINE1 | 0x03e4)
	objA0.box_size.x = 0x20
	objA0.box_size.y = 0x40
	objA0.value32 = objA0.position.y.u16
	objA0.animation.sprite = 0x06
	u16[A0 + 0x30] = 0x50
	objA0.flags2a |= 0x80

	if (allocDynamicObjectAfterA0())
	{
		objA1.update_address = 0x030dec
		objA1.mapping_offset = 0x22f998
		objA1.sprite_attributes = (sprite_attribute.PALETTE.LINE1 | 0x03e4)
		objA1.render_flags = objA0.render_flags
		objA1.box_size.x = 0x20
		objA1.box_size.x = 0x30
		objA1.sprite_priority = 0x0280
		objA1.position.x.u16 = objA0.position.x.u16
		objA1.position.y.u16 = objA0.position.y.u16
		u16[A1 + 0x3c] = A0.u16
	}

	objA0.update_address = 0x030b58
	fn030b58()
}


//# address-hook(0x030b58) end(0x030c00)
function void fn030b58()
{
	u16 dx1 = u16[0xffffb000 + 0x10] - objA0.position.x.u16 + 0x20
	u16 dx2 = u16[0xffffb04a + 0x10] - objA0.position.x.u16 + 0x20
	if (dx1 >= 0x40 && dx2 >= 0x40)
	{
		if (u16[A0 + 0x30] != 0x50)
		{
			u16[A0 + 0x30] += 8
		}
	}
	else
	{
		if (u8[A0 + 0x34] != 0)
		{
			objA0.animation.sprite = 7
			objA0.sprite_priority = 0x80
			if (u16[A0 + 0x36] != 0)
			{
				--u16[A0 + 0x36]
			}
			else if (u16[A0 + 0x30] != 0)
			{
				u16[A0 + 0x30] -= 8
			}
			else
			{
				objA0.update_address = 0x030c06
				u16[A0 + 0x36] = 0x3b
			}

			fn030ce0()
		}
		else
		{
			u16[A0 + 0x36] = 0x13
			objA0.animation.sprite = 0x06
			objA0.sprite_priority = 0x0200

			if (u16[A0 + 0x30] > 0x18)
			{
				u16[A0 + 0x30] -= 8
			}
			else
			{
				fn030ce0()
			}
		}
	}

	objA0.position.y.u16 = u16[A0 + 0x30] + objA0.value32
	D1.u16 = 0x20
	D3.u16 = 0x11
	D4.u16 = objA0.position.x.u16
	PlatformCheckClimbOn()

	DrawOrUnloadObject()
}


//# address-hook(0x030c06) end(0x030c76)
function void fn030c06()
{
	if (u16[A0 + 0x36] != 0)
	{
		--u16[A0 + 0x36]
		fn030ce0()
	}
	else
	{
		if (u16[A0 + 0x30] == 0x50)
		{
			u8[A0 + 0x34] = 0
			objA0.update_address = 0x030b58
			playSound(SFX_SPINDASH_RELEASE)
		}
		else
		{
			if (u16[A0 + 0x30] == 0x18)
			{
				fn030c7c()
				objA0.animation.sprite = 6
				objA0.sprite_priority = 0x0200
			}
			u16[A0 + 0x30] += 8
		}
	}

	objA0.position.y.u16 = u16[A0 + 0x30] + objA0.value32
	if (u16[A0 + 0x30] <= 0x18)
	{
		D1.u16 = 0x20
		D3.u16 = 0x11
		D4.u16 = objA0.position.x.u16
		PlatformCheckClimbOn()
	}

	DrawOrUnloadObject()
}


//# address-hook(0x030c7c) end(0x030cde)
function void fn030c7c()
{
	A1 = 0xffffb000
	D6 = 3		// object.flag.P1_ON_OBJECT
	fn030c8c()

	A1 = 0xffffb04a
	D6 = 4		// object.flag.P2_ON_OBJECT
	fn030c8c()
}


function void fn030c8c()
{
	u8 bit = (1 << D6.u8)
	if (u8[A0 + 0x35] & bit)
	{
		u8[A0 + 0x35] &= ~bit
		objA1.velocity.x = (objA0.flags2a & 0x01) ? -0x1000 : 0x1000
		objA1.velocity.y = 0
		objA1.groundspeed = objA1.velocity.x
		objA1.state = char.state.RUNNING
		u8[A1 + 0x2e] = 0
		u8[A1 + 0x2a] &= ~char.flag.ON_OBJECT
		objA0.flags2a &= ~bit
	}
	else if (objA0.flags2a & bit)
	{
		objA0.flags2a &= ~bit
		u8[A1 + 0x2a] &= ~char.flag.ON_OBJECT
		u8[A1 + 0x2a] |= char.flag.IN_AIR
	}
}


//# address-hook(0x030ce0) end(0x030dea)
function void fn030ce0()
{
	A1 = 0xffffb000
	D6 = 3		// object.flag.P1_ON_OBJECT
	D0.u8 = control.player1.pressed
	fn030cf8()

	A1 = 0xffffb04a
	D6 = 4		// object.flag.P2_ON_OBJECT
	D0.u8 = control.tails.pressed
	fn030cf8()
}


function void fn030cf8()
{
	u8 bit = (1 << D6.u8)

#if STANDALONE
	// Bug fix: If character gets hurt, don't launch him
	if (u8[A1 + 0x05] != 0x02)
	{
		u8[A0 + 0x35] &= ~bit
		if (u8[A0 + 0x35] == 0)
		{
			u8[A0 + 0x34] = 0
		}
	}
#endif

	if (u8[A0 + 0x35] & bit)
	{
		// Check if jump button pressed
		if (D0.u8 & CONTROL_ABC)
		{
			u8[A0 + 0x35] &= ~bit
			objA0.flags2a &= ~bit
			objA1.velocity.x = (objA0.flags2a & 0x01) ? -0x800 : 0x800
			objA1.velocity.y = -0x400
			objA1.groundspeed = objA1.velocity.x
			u8[A1 + 0x2e] = 0
			u8[A1 + 0x2a] &= ~char.flag.ON_OBJECT
			u8[A1 + 0x2a] |= char.flag.IN_AIR
			if (u8[A0 + 0x35] == 0)
			{
				u8[A0 + 0x34] = 0
			}
		}
		return
	}

	if (objA0.flags2a & bit)
	{
		if (u8[A0 + 0x34] == 0)
		{
			D0.u16 = objA1.position.x.u16 - objA0.position.x.u16 + 8
			if (D0.u16 >= 0x10)
				return
		}

		if (u8[A1 + 0x2e] == 0 && debug_mode.state == 0)
		{
			u8[A0 + 0x35] |= bit

			playSound(SFX_ROLL)

			u8[A1 + 0x20] = 0
			objA1.hitbox_extends.y = (objA1.update_address == addressof(Character.BaseUpdate.Tails)) ? char.hitbox.y.UPRIGHT_TAILS : char.hitbox.y.UPRIGHT		// Checking for Tails, might be clearer to check `u8[A1 + 0x38] == CHARACTER_TAILS` instead
			objA1.hitbox_extends.x = char.hitbox.x.UPRIGHT
			objA1.flags2a &= ~(char.flag.FACING_LEFT | char.flag.ROLLING | char.flag.PUSHING)
		#if STANDALONE
			objA1.flags2a &= ~char.flag.IN_AIR	// Fix for wrong placement of the character if bubble-bouncing onto the hand launcher, #contributed by iCloudius
		#endif
			u8[A1 + 0x2e] = 1
			objA1.position.x.u16 = objA0.position.x.u16 - 2
			u16[A1 + 0x1c] = 0x1000
			if (objA0.flags2a & 0x01)
			{
				objA1.position.x.u16 += 4
				objA1.groundspeed = -objA1.groundspeed
				objA1.flags2a |= char.flag.FACING_LEFT
			}
			u8[A0 + 0x34] = 1
		}
	}
}


//# address-hook(0x030dec) end(0x030e12)
function void fn030dec()
{
	A1 = 0xffff0000 + u16[A0 + 0x3c]
	objA0.position.y.u16 = objA1.position.y.u16
	if (u16[A1 + 0x30] > 0x18)
		return

	++objA0.animation.sprite
	if (objA0.animation.sprite >= 6)
		objA0.animation.sprite = 0

	DrawOrUnloadObject()
}
